#include "displayable.h"
#include <stdlib.h>
#include <stdio.h>

#include "../actions/velocity.h"

/**********************************************************/
/*                  Constructeurs                         */
/**********************************************************/

Displayable::Displayable(int aType)
{
    type=aType;
    state=1;
    translation= new Vectorf(0,0,0);
    rotation = new Vectorf(0,0,0);
    movable=0;
    gravity=0;
    valGravity=0.0;
    barycentre=new Vectorf(0,0,0);
}

Displayable::Displayable(int aType, Vectorf aTranslation)
{
    type=aType;
    state=1;
    translation= new Vectorf(aTranslation);
    rotation= new Vectorf(0,0,0);
    movable=0;
    gravity=0;
    valGravity=0.0; barycentre=new Vectorf(0,0,0);
}

Displayable::Displayable(int aType, Vectorf aTranslation, Vectorf aRotation)
{
    valGravity=0.0;
    movable=0;
    type=aType;
    state=1;
    translation= new Vectorf(aTranslation);
    rotation = new Vectorf(aRotation);
    gravity=0; barycentre=new Vectorf(0,0,0);

}

Displayable::~Displayable()
{

}

int Displayable::SetColor(int indiceVertex, Vectorf color)
{
        glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);

        float * verticesColors = (float *) glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);

        for(int i=0;i<dimensionColors;i++)
        {
                verticesColors[(indiceVertex*dimensionColors)+i]=color.Array()[i];
        }

        glUnmapBuffer(GL_ARRAY_BUFFER);
}

int Displayable::SetVertex(int indiceVertex, Vectorf coordinate)
{
        /*
         * 	Dans un premier temps, on définit le buffer courant : le buffer de sommets
         */

        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);

        /*
         * 	Ensuite, on transforme le Vector en tableau de floats à l'aide de la méthode ToArray();
         */

        float * arg = coordinate.Array();

        /*
         * 	La méthode glMapBuffer permet de récupérer dans un tableau les données du buffer courant
         */

        float * vertices = (float *) glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);

        for(int i=0;i<dimensionVertex;i++)
        {
            vertices[(indiceVertex*dimensionVertex)+i]=arg[i];
        }

        glUnmapBuffer(GL_ARRAY_BUFFER);
}

Vectorf Displayable::GetVertex(int indiceVertex)
{
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);

        Vectorf vectorTemp;

        float * vertices = (float *) glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);

        if(dimensionVertex==1)
        {
                vectorTemp.x(vertices[dimensionVertex*indiceVertex]);
        }
        else if (dimensionVertex==2)
        {
                vectorTemp.x(vertices[indiceVertex*dimensionVertex]);
                vectorTemp.y(vertices[(indiceVertex*dimensionVertex)+1]);
        }
        else if (dimensionVertex==3)
        {
                vectorTemp.x(vertices[indiceVertex*dimensionVertex]);
                vectorTemp.y(vertices[(indiceVertex*dimensionVertex)+1]);
                vectorTemp.z(vertices[(indiceVertex*dimensionVertex)+2]);
        }

        glUnmapBuffer(GL_ARRAY_BUFFER);

        return vectorTemp;
}

void Displayable::SetMovable(Vectorf * vec)
{
    movable=1;
    velocity= new Velocity(vec);
}

void Displayable::Update()
{
    for(int i=0;i<actions.size();i++)
    {
        if(actions.at(i)->end==1)
        {
            actions.erase(actions.begin()+i);
        }
        else
        {
            actions[i]->Do();

        }
    }
}

void Displayable::CheckInputDelegates()
{
    for(int j=0;j<inputDelegates.size();j++)
    {
        inputDelegates.at(j)->Update();
    }
}

void Displayable::CheckDelegates()
{
    for(int j=0;j<delegates.size();j++)
    {
        delegates.at(j)->Update();
    }
    for(int i=0;i<collisions.size();i++)
    {
        if(collisions.at(i)->state==-1)
        {
           collisions.erase(collisions.begin()+i);
        }
        else
        {

            collisionIndex=i;

        }
    }
}

AABB * Displayable::SetAABB()
{
    Vectorf * min= new Vectorf(GetVertex(0));
    Vectorf * max= new Vectorf(GetVertex(0));

    for(int i=1;i<vertexCount;i++)
    {
        Vectorf * temp= new Vectorf(GetVertex(i));

        if(temp->x()<min->x())
        {
            min->x(temp->x());
        }
        if(temp->x()>max->x())
        {
            max->x(temp->x());
        }

        if(temp->y()<min->x())
        {
            min->y(temp->y());
        }
        if(temp->y()>max->y())
        {
            max->y(temp->y());
        }

        if(temp->z()<min->z())
        {
            min->z(temp->z());
        }
        if(temp->z()>max->z())
        {
            max->z(temp->z());
        }
    }

    return new AABB(min,max);

}
